home *** CD-ROM | disk | FTP | other *** search
/ Hardcore Visual Basic 5.0 (2nd Edition) / Hardcore Visual Basic 5.0 - Second Edition (1997)(Microsoft Press).iso / Code / sortold.bas < prev    next >
BASIC Source File  |  1997-06-14  |  10KB  |  294 lines

  1. Attribute VB_Name = "MSortOld"
  2. Option Explicit
  3.  
  4. '$ Uses UTILITY.BAS
  5.  
  6. ' Old iterative QuickSort algorithm
  7. Public Sub SortArrayO(aTarget() As Variant, _
  8.                       Optional vFirst As Variant, Optional vLast As Variant)
  9.     Dim iFirst As Long, iLast As Long
  10.     If IsMissing(vFirst) Then iFirst = LBound(aTarget) Else iFirst = vFirst
  11.     If IsMissing(vFirst) Then iLast = UBound(aTarget) Else iLast = vLast
  12.     
  13.     Dim iLo As Long, iHi As Long, stack As New CStack
  14.     Do
  15.         Do
  16.             ' Keep swapping from ends until first and last meet in the middle
  17.             If iFirst < iLast Then
  18.                 ' If we're in the middle and out of order, swap
  19.                 If iLast - iFirst = 1 Then
  20.                     If SortCompare(aTarget(iFirst), aTarget(iLast)) > 0 Then
  21.                         SortSwap aTarget(iFirst), aTarget(iLast)
  22.                     End If
  23.                 Else
  24.                     ' Split at some random point
  25.                     SortSwap aTarget(iLast), aTarget(Random(iFirst, iLast))
  26.                     ' Swap high values below the split for high values above
  27.                     iLo = iFirst: iHi = iLast
  28.                     Do
  29.                         ' Find find any low value larger than split
  30.                         Do While (iLo < iHi) And SortCompare(aTarget(iLo), aTarget(iLast)) <= 0
  31.                             iLo = iLo + 1
  32.                         Loop
  33.                         ' Find any high value smaller than split
  34.                         Do While (iHi > iLo) And SortCompare(aTarget(iHi), aTarget(iLast)) >= 0
  35.                             iHi = iHi - 1
  36.                         Loop
  37.                         ' Swap the too high low value for the too low high value
  38.                         If iLo < iHi Then SortSwap aTarget(iLo), aTarget(iHi)
  39.                     Loop While iLo < iHi
  40.                     ' Current item (iLo) is always larger than split (iLast), so swap
  41.                     SortSwap aTarget(iLo), aTarget(iLast)
  42.                     ' Push range markers of smaller part for later processing
  43.                     If (iLo - iFirst) < (iLast - iLo) Then
  44.                         stack.Push iLo + 1
  45.                         stack.Push iLast
  46.                         iLast = iLo - 1
  47.                     Else
  48.                         stack.Push iFirst
  49.                         stack.Push iLo - 1
  50.                         iFirst = iLo + 1
  51.                     End If
  52.                     ' Exit from inner loop to process smaller part
  53.                     Exit Do
  54.                 End If
  55.             End If
  56.             
  57.             ' If stack empty, Exit outer loop
  58.             If stack.Count = 0 Then Exit Sub
  59.             ' Else pop first and last from last deferred section
  60.             iLast = stack.Pop
  61.             iFirst = stack.Pop
  62.         Loop
  63.     Loop
  64.  
  65. End Sub
  66.  
  67. ' Old recursive QuickSort algorithm
  68. Sub SortArrayRecO(aTarget() As Variant, _
  69.               iFirst As Long, iLast As Long)
  70.     If iFirst < iLast Then
  71.  
  72.         ' Only two elements in this subdivision; exchange if
  73.         ' they are out of order, and end recursive calls
  74.         If iLast - iFirst = 1 Then
  75.             If SortCompare(aTarget(iFirst), aTarget(iLast)) > 0 Then
  76.                 SortSwap aTarget(iFirst), aTarget(iLast)
  77.             End If
  78.         Else
  79.  
  80.             Dim i As Long, j As Long
  81.  
  82.             ' Pick pivot element at random and move to end
  83.             SortSwap aTarget(iLast), aTarget(Random(iFirst, iLast))
  84.             i = iFirst: j = iLast
  85.             Do
  86.  
  87.                 ' Move in from both sides toward pivot element
  88.                 Do While (i < j) And _
  89.                          SortCompare(aTarget(i), aTarget(iLast)) <= 0
  90.                     i = i + 1
  91.                 Loop
  92.                 Do While (j > i) And _
  93.                          SortCompare(aTarget(j), aTarget(iLast)) >= 0
  94.                     j = j - 1
  95.                 Loop
  96.  
  97.                 ' If you haven't reached pivot element, it means
  98.                 ' that the two elements on either side are out of
  99.                 ' order, so swap them
  100.                 If i < j Then
  101.                     SortSwap aTarget(i), aTarget(j)
  102.                 End If
  103.             Loop While i < j
  104.  
  105.             ' Move pivot element back to its proper place
  106.             SortSwap aTarget(i), aTarget(iLast)
  107.  
  108.             ' Recursively call SortArrayO (pass smaller
  109.             ' subdivision first to use less stack space)
  110.             If (i - iFirst) < (iLast - i) Then
  111.                 SortArrayRecO aTarget(), iFirst, i - 1
  112.                 SortArrayRecO aTarget(), i + 1, iLast
  113.             Else
  114.                 SortArrayRecO aTarget(), i + 1, iLast
  115.                 SortArrayRecO aTarget(), iFirst, i - 1
  116.             End If
  117.         End If
  118.     End If
  119.  
  120. End Sub
  121.  
  122. ' QuickSort algorithm
  123. Sub SortCollectionO(nTarget As Collection, iFirst As Long, iLast As Long)
  124.     If iFirst < iLast Then
  125.  
  126.         ' Only two elements in this subdivision; exchange if
  127.         ' they are out of order, and end recursive calls
  128.         If iLast - iFirst = 1 Then
  129.             If SortCompare(nTarget(iFirst), nTarget(iLast)) > 0 Then
  130.                 CollectionSwap nTarget, iFirst, iLast
  131.             End If
  132.         Else
  133.  
  134.             Dim i As Long, j As Long
  135.  
  136.             ' Pick pivot element at random and move to end
  137.             CollectionSwap nTarget, iLast, Random(iFirst, iLast)
  138.             i = iFirst: j = iLast
  139.             Do
  140.  
  141.                 ' Move in from both sides toward pivot element
  142.                 Do While (i < j) And _
  143.                     SortCompare(nTarget(i), nTarget(iLast)) <= 0
  144.                     i = i + 1
  145.                 Loop
  146.                 Do While (j > i) And _
  147.                     SortCompare(nTarget(j), nTarget(iLast)) >= 0
  148.                     j = j - 1
  149.                 Loop
  150.  
  151.                 ' If you haven't reached pivot element, it means
  152.                 ' that the two elements on either side are out of
  153.                 ' order, so swap them
  154.                 If i < j Then
  155.                     CollectionSwap nTarget, i, j
  156.                 End If
  157.             Loop While i < j
  158.  
  159.             ' Move pivot element back to its proper place
  160.             CollectionSwap nTarget, i, iLast
  161.  
  162.             ' Recursively call SortCollectionO (pass smaller
  163.             ' subdivision first to use less stack space)
  164.             If (i - iFirst) < (iLast - i) Then
  165.                 SortCollectionO nTarget, iFirst, i - 1
  166.                 SortCollectionO nTarget, i + 1, iLast
  167.             Else
  168.                 SortCollectionO nTarget, i + 1, iLast
  169.                 SortCollectionO nTarget, iFirst, i - 1
  170.             End If
  171.         End If
  172.     End If
  173.  
  174. End Sub
  175.  
  176. Function BSearchArrayO(av() As Variant, vKey As Variant, _
  177.                       iPos As Long) As Boolean
  178.     Dim iLo As Long, iHi As Long
  179.     Dim iComp As Long, iMid As Long
  180.     iLo = LBound(av): iHi = UBound(av)
  181.     Do
  182.         iMid = iLo + ((iHi - iLo) \ 2)
  183.         iComp = SortCompare(av(iMid), vKey)
  184.         Select Case iComp
  185.         Case 0
  186.             ' Item found
  187.             iPos = iMid
  188.             BSearchArrayO = True
  189.             Exit Function
  190.         Case Is > 0
  191.             ' Item is in lower half
  192.             iHi = iMid
  193.             If iLo = iHi Then Exit Do
  194.         Case Is < 0
  195.             ' Item is in upper half
  196.             iLo = iMid + 1
  197.             If iLo > iHi Then Exit Do
  198.         End Select
  199.     Loop
  200.     ' Item not found, but return position to insert
  201.     iPos = iMid - (iComp < 0)
  202.     BSearchArrayO = False
  203.         
  204. End Function
  205.  
  206. Function BSearchCollectionO(n As Collection, vKey As Variant, _
  207.                            iPos As Long) As Boolean
  208.     Dim iLo As Long, iHi As Long
  209.     Dim iComp As Long, iMid As Long
  210.     iLo = 1: iHi = n.Count
  211.     Do
  212.         iMid = iLo + ((iHi - iLo) \ 2)
  213.         iComp = SortCompare(n(iMid), vKey)
  214.         Select Case iComp
  215.         Case 0
  216.             ' Item found
  217.             iPos = iMid
  218.             BSearchCollectionO = True
  219.             Exit Function
  220.         Case Is > 0
  221.             ' Item is in lower half
  222.             iHi = iMid
  223.             If iLo = iHi Then Exit Do
  224.         Case Is < 0
  225.             ' Item is in upper half
  226.             iLo = iMid + 1
  227.             If iLo > iHi Then Exit Do
  228.         End Select
  229.     Loop
  230.     ' Item not found, but return position to insert
  231.     iPos = iMid - (iComp < 0)
  232.     BSearchCollectionO = False
  233.         
  234. End Function
  235.  
  236. Sub ShuffleArrayO(av() As Variant)
  237.     Dim iFirst As Long, iLast As Long
  238.     iFirst = LBound(av): iLast = UBound(av)
  239.         
  240.     ' Randomize array
  241.     Dim i As Long, v As Variant, iRnd As Long
  242.     For i = iLast To iFirst + 1 Step -1
  243.         ' Swap random element with last element
  244.         iRnd = Random(iFirst, i)
  245.         SortSwap av(i), av(iRnd)
  246.     Next
  247. End Sub
  248.  
  249. Sub ShuffleCollectionO(n As Collection)
  250.     Dim iFirst As Long, iLast As Long
  251.     iFirst = 1: iLast = n.Count
  252.     
  253.     ' Randomize collection
  254.     Dim i As Long, v As Variant, iRnd As Long
  255.     For i = iLast To iFirst + 1 Step -1
  256.         ' Swap random element with last element
  257.         iRnd = Random(iFirst, i)
  258.         CollectionSwap n, i, iRnd
  259.     Next
  260. End Sub
  261.  
  262. ' Define fSortCompareDef to use default SortCompare
  263. #If fSortCompareDef Then
  264. Private Function SortCompare(ByVal v1 As Variant, _
  265.                              ByVal v2 As Variant) As Long
  266.     If v1 < v2 Then
  267.         SortCompare = -1
  268.     ElseIf v1 = v2 Then
  269.         SortCompare = 0
  270.     Else
  271.         SortCompare = 1
  272.     End If
  273. End Function
  274. #End If
  275.  
  276. ' Define fSortSwapNoDef if you provide your own swap routine
  277. #If fSortSwapNoDef = 0 Then
  278. Sub SortSwap(v1 As Variant, v2 As Variant)
  279.     Dim vT As Variant
  280.     vT = v1
  281.     v1 = v2
  282.     v2 = vT
  283. End Sub
  284. #End If
  285.  
  286. Sub CollectionSwap(n As Collection, i1 As Long, i2 As Long)
  287.     Dim vT As Variant
  288.     vT = n(i1)
  289.     n.Add n(i2), , , i1
  290.     n.Remove i1
  291.     n.Add vT, , , i2
  292.     n.Remove i2
  293. End Sub
  294.